#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/bio.h>
#include <linux/init.h>
#include <linux/compiler.h>
#include <linux/blktrace_api.h>	
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/cgroup.h>
#include <linux/elevator.h>
#include <linux/ktime.h>
#include <linux/rbtree.h>
#include <linux/ioprio.h>
#include <linux/sbitmap.h>
#include <linux/delay.h>
#include <linux/backing-dev.h>

#include <trace/events/block.h> 


#include "blk.h"
#include "blk-mq.h"
#include "blk-mq-tag.h"
#include "blk-mq-sched.h"


enum row_queue_prio {
	ROWQ_PRIO_HIGH_READ = 0,
	ROWQ_PRIO_HIGH_SWRITE,
	ROWQ_PRIO_REG_READ,
	ROWQ_PRIO_REG_SWRITE,
	ROWQ_PRIO_REG_WRITE,
	ROWQ_PRIO_LOW_READ,
	ROWQ_PRIO_LOW_SWRITE,
	ROWQ_MAX_PRIO,
};

struct row_queue_params {
	bool idling_enabled;
	int quantum;
	bool is_urgent;
};

struct rowq_idling_data {
	ktime_t			last_insert_time;
	bool			begin_idling;
};

struct row_queue {
	struct row_data		*rdata;
	struct list_head	fifo;
	enum row_queue_prio	prio;
	unsigned int		nr_dispatched;
	unsigned int		nr_req;
	int			disp_quantum;
	struct rowq_idling_data	idle_data;
};

struct idling_data {
	s64				idle_time_ms;
	s64				freq_ms;
	struct hrtimer			hr_timer;
	struct work_struct		idle_work;
	enum row_queue_prio		idling_queue_idx;
};

struct starvation_data {
	int				starvation_limit;
	int				starvation_counter;
};

struct row_data {
	struct request_queue		*dispatch_queue;
	struct row_queue row_queues[ROWQ_MAX_PRIO];
	struct idling_data		rd_idle_data;
	unsigned int			nr_reqs[2];
	bool				urgent_in_flight;
	struct request			*pending_urgent_rq;
	int				last_served_ioprio_class;
#define	ROW_REG_STARVATION_TOLLERANCE	5000
	struct starvation_data		reg_prio_starvation;
#define	ROW_LOW_STARVATION_TOLLERANCE	10000
	struct starvation_data		low_prio_starvation;
	unsigned int			cycle_flags;
};

static void row_add_request(struct request_queue *q, struct request *rq)
{
	return;
}

static int row_reinsert_req(struct request_queue *q, struct request *rq)
{
	return 0;
}

static void row_completed_req(struct request_queue *q, struct request *rq)
{
	return;
}

static bool row_urgent_pending(struct request_queue *q)
{
	return 0;
}

static void row_remove_request(struct row_data *rd, struct request *rq)
{
	return;
}

static void row_dispatch_insert(struct row_data *rd, struct request *rq)
{
	return;
}

static int row_get_ioprio_class_to_serve(struct row_data *rd, int force)
{
	return 0;
}

static void row_restart_cycle(struct row_data *rd, int start_idx, int end_idx)
{
	return;
}

static int row_get_next_queue(struct request_queue *q, struct row_data *rd, int start_idx, int end_idx)
{
	return 0;
}

static int row_dispatch_requests(struct request_queue *q, int force)
{
	return 0;
}

static int row_init_queue(struct request_queue *q, struct elevator_type *e)
{
	return 0;
}

static void row_exit_queue(struct elevator_queue *e)
{
	return;
}

static void row_merged_requests(struct request_queue *q, struct request *rq, 				 struct request *next)
{
	return;
}

static int row_set_request(struct request_queue *q, struct request *rq, struct bio *bio, gfp_t gfp_mask)
{
	return 0;
}

static bool row_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio)
{
	return 0;
}



static struct elevator_type iosched_row_mq = {
	.ops.mq = {

	},
	.icq_size = sizeof(struct io_cq),
	.icq_align = __alignof__(struct io_cq),
	.elevator_name = "row-mq",
	.elevator_owner = THIS_MODULE,

};

static int __init row_init(void)
{
    elv_register(&iosched_row_mq);
    return 0;
}
    
static void __exit row_exit(void)
{
    elv_unregister(&iosched_row_mq);
}


module_init(row_init);
module_exit(row_exit);

MODULE_AUTHOR("xxx");
MODULE_LICENSE("GPL");
